#include "kchartform.h"

#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QMouseEvent>
#include <QToolTip>
#include <QDateTime>
#include <QtMath>

KChartForm::KChartForm(QWidget *parent)
    : QWidget(parent)
{

    // 初始化定时器，每2秒生成一个新的K线数据
    connect(m_timer, &QTimer::timeout, this, &KChartForm::generateNewKlineData);
    m_timer->setInterval(2000);

    // 生成一些初始数据
    QDateTime now = QDateTime::currentDateTime();
    double price = 100.0;
    for (int i = 30; i >= 0; --i) {
        KlineData data;
        data.time = now.addSecs(-i * 2);
        data.open = price;
        data.high = price + rand() % 5;
        data.low = price - rand() % 5;
        data.close = data.low + rand() % ((int)(data.high - data.low + 1));
        data.volume = 1000 + rand() % 9000;

        price = data.close;
        m_klineData.append(data);
    }
}

KChartForm::~KChartForm()
{
}


void KChartForm::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    if (m_klineData.isEmpty()) {
        return;
    }

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);

    // 获取绘图区域
    QRectF chartRect = getChartRect();

    // 绘制背景
    painter.fillRect(chartRect, QColor(245, 245, 245));

    // 计算价格范围，增加一些边距使图表更美观
    double minPrice = m_klineData[0].low;
    double maxPrice = m_klineData[0].high;
    for (const auto &data : m_klineData) {
        minPrice = qMin(minPrice, data.low);
        maxPrice = qMax(maxPrice, data.high);
    }
    double priceRange = maxPrice - minPrice;
    minPrice -= priceRange * 0.1;  // 10%的边距
    maxPrice += priceRange * 0.1;

    // 绘制坐标轴和网格线
    painter.save();
    painter.setPen(QPen(QColor(200, 200, 200), 1));

    // X轴 - 时间轴
    painter.drawLine(chartRect.left(), chartRect.bottom(),
                     chartRect.right(), chartRect.bottom());

    // Y轴 - 价格轴
    painter.drawLine(chartRect.left(), chartRect.top(),
                     chartRect.left(), chartRect.bottom());

    // 绘制水平网格线和价格标签
    int yGridCount = 5;
    for (int i = 0; i <= yGridCount; ++i) {
        double ratio = (double)i / yGridCount;
        double price = maxPrice - (maxPrice - minPrice) * ratio;
        double y = chartRect.top() + (chartRect.height() * ratio);

        // 网格线
        painter.drawLine(chartRect.left(), y, chartRect.right(), y);

        // 价格标签
        painter.drawText(chartRect.left() - m_marginLeft + 5, y + 5,
                         QString::number(price, 'f', 2));
    }

    // 绘制垂直网格线和时间标签
    int xGridCount = qMin(10, (int)m_klineData.size() - 1);
    int step = (m_klineData.size() - 1) / xGridCount;
    for (int i = 0; i < m_klineData.size(); i += step) {
        double x = timeToX(i, chartRect);

        // 网格线
        painter.drawLine(x, chartRect.top(), x, chartRect.bottom());

        // 时间标签
        QString timeStr = m_klineData[i].time.toString("HH:mm:ss");
        painter.drawText(x - 30, chartRect.bottom() + 15, timeStr);
    }
    painter.restore();

    // 绘制K线
    for (int i = 0; i < m_klineData.size(); ++i) {
        const auto &data = m_klineData[i];
        double x = timeToX(i, chartRect);

        // 绘制影线
        double highY = priceToY(data.high, chartRect);
        double lowY = priceToY(data.low, chartRect);
        painter.save();
        painter.setPen(QPen(Qt::black, 1));
        painter.drawLine(x, highY, x, lowY);
        painter.restore();

        // 绘制实体
        double openY = priceToY(data.open, chartRect);
        double closeY = priceToY(data.close, chartRect);

        QRectF candleRect(x - m_candleWidth / 2,
                          qMin(openY, closeY),
                          m_candleWidth,
                          qAbs(closeY - openY));

        painter.save();
        if (data.close >= data.open) {
            // 上涨，红色
            painter.setBrush(QBrush(Qt::red));
            painter.setPen(QPen(Qt::red, 1));
        } else {
            // 下跌，绿色
            painter.setBrush(QBrush(Qt::green));
            painter.setPen(QPen(Qt::green, 1));
        }

        // 如果是当前鼠标指向的K线，绘制边框突出显示
        if (i == m_hoveredIndex) {
            painter.drawRect(candleRect.adjusted(-1, -1, 1, 1));
        }

        painter.drawRect(candleRect);
        painter.restore();
    }

    // 如果有选中的K线，绘制详细信息
    if (m_hoveredIndex >= 0 && m_hoveredIndex < m_klineData.size()) {
        const auto &data = m_klineData[m_hoveredIndex];
        QString info = QString("时间: %1\n开盘: %2\n最高: %3\n最低: %4\n收盘: %5")
                           .arg(data.time.toString("yyyy-MM-dd HH:mm:ss"))
                           .arg(data.open, 0, 'f', 2)
                           .arg(data.high, 0, 'f', 2)
                           .arg(data.low, 0, 'f', 2)
                           .arg(data.close, 0, 'f', 2);

        QToolTip::showText(mapToGlobal(QPoint(10, 10)), info, this);
    }
}

void KChartForm::mouseMoveEvent(QMouseEvent *event)
{
    int index = findKlineIndex(event->pos());
    if (index != m_hoveredIndex) {
        m_hoveredIndex = index;
        update();  // 重绘以更新提示信息
    }
    KChartForm::mouseMoveEvent(event);
}

void KChartForm::resizeEvent(QResizeEvent *event)
{
    update();  // 窗口大小改变时重绘
    KChartForm::resizeEvent(event);
}

void KChartForm::generateNewKlineData()
{
    if (m_klineData.isEmpty()) {
        return;
    }

    KlineData newData;
    newData.time = QDateTime::currentDateTime();

    // 以上一个K线的收盘价为基础生成新的价格
    const KlineData &lastData = m_klineData.last();
    newData.open = lastData.close;
    newData.high = newData.open + generateRandomPrice(0) * 2;
    newData.low = newData.open - generateRandomPrice(0) * 2;
    newData.close = newData.low + generateRandomPrice(newData.high - newData.low);
    newData.volume = 1000 + rand() % 9000;

    m_klineData.append(newData);

    // 保持数据量在100个以内，防止内存占用过大
    if (m_klineData.size() > 100) {
        m_klineData.removeFirst();
    }

    update();  // 重绘图表
}

void KChartForm::on_startStopBtn_clicked()
{
    if (m_isRunning) {
        m_timer->stop();
        //ui->startStopBtn->setText("开始");
    } else {
        m_timer->start();
        //ui->startStopBtn->setText("停止");
    }
    m_isRunning = !m_isRunning;
}

void KChartForm::on_clearBtn_clicked()
{
    m_klineData.clear();
    m_hoveredIndex = -1;
    update();
}

QRectF KChartForm::getChartRect() const
{
    return QRectF(m_marginLeft, m_marginTop,
                  width() - m_marginLeft - m_marginRight,
                  height() - m_marginTop - m_marginBottom);
}

double KChartForm::priceToY(double price, const QRectF &rect) const
{
    if (m_klineData.isEmpty()) return 0;

    // 计算价格范围
    double minPrice = m_klineData[0].low;
    double maxPrice = m_klineData[0].high;
    for (const auto &data : m_klineData) {
        minPrice = qMin(minPrice, data.low);
        maxPrice = qMax(maxPrice, data.high);
    }
    double priceRange = maxPrice - minPrice;
    if (priceRange <= 0) return rect.top();

    // 转换价格到Y坐标（注意Y轴是向下增长的）
    return rect.bottom() - ((price - minPrice) / priceRange) * rect.height();
}

double KChartForm::timeToX(int index, const QRectF &rect) const
{
    if (m_klineData.isEmpty()) return 0;

    int count = m_klineData.size();
    double totalWidth = rect.width() - m_candleWidth;
    double step = totalWidth / qMax(1, count - 1);

    return rect.left() + m_candleWidth / 2 + index * step;
}

int KChartForm::findKlineIndex(const QPoint &pos)
{
    if (m_klineData.isEmpty()) return -1;

    QRectF chartRect = getChartRect();
    if (!chartRect.contains(pos)) return -1;

    // 计算点击位置对应的K线索引
    int count = m_klineData.size();
    double totalWidth = chartRect.width() - m_candleWidth;
    double step = totalWidth / qMax(1, count - 1);

    // 计算距离左侧的偏移
    double offset = pos.x() - chartRect.left() - m_candleWidth / 2;
    if (offset < 0) return 0;

    int index = qRound(offset / step);
    if (index >= count) index = count - 1;

    // 检查是否在K线范围内
    double x = timeToX(index, chartRect);
    if (qAbs(pos.x() - x) < m_candleWidth + m_candleSpace) {
        return index;
    }

    return -1;
}

double KChartForm::generateRandomPrice(double lastPrice)
{
    // 生成0到lastPrice之间的随机数，模拟价格波动
    if (lastPrice <= 0) {
        return QRandomGenerator::global()->generateDouble() * 2;
    }
    return QRandomGenerator::global()->generateDouble() * lastPrice;
}

